use std::fs::File;
use std::io::Read;

use yaml_rust::{Yaml, YamlLoader};

const APPLICATION_FILE:&'static str = "application.yml";

///服务启动配置
pub struct ApplicationConfig {
    pub debug: bool,
    ///port
    pub port: i64,
    ///当前服务地址
    pub server_url: String,
    // ///redis地址
    // pub redis_url: String,
    ///mysql地址
    pub mysql_url: String,
}

///默认配置
impl Default for ApplicationConfig {
    fn default() -> Self {
        let mut yml_data = String::new();
        File::open(APPLICATION_FILE)
            .or(File::open( format!("src/{}", APPLICATION_FILE)))
            .expect("application.yml not exist!")
            .read_to_string(&mut yml_data);

        let docs = YamlLoader::load_from_str(&yml_data).unwrap();
        let yml = &docs[0];
        let app_name = get_value(yml, "application.name").as_str().unwrap_or("admin-rs");
        let debug = get_value(yml, "application.debug").as_bool().unwrap_or(true);
        println!("{} Run debug:{}", app_name, debug);
        //读取配置
        Self {
            debug: debug,
            port: get_value(yml, "application.port").as_i64().unwrap_or(9100).to_owned(),

            server_url: String::from(""),
            mysql_url: get_value(yml, "datasource.url").as_str().unwrap_or("").to_owned(),
        }
    }
}

/// Get the value of Yaml
/// yml Yaml
/// key config key, such as: "name", "server.port"
/// return Yaml or panic if key not exist.
fn get_value<'a >(yml: &'a Yaml, key: &str) -> &'a Yaml {
    let split = key.split(".");
    let mut option = Some(yml);
    for x in split.into_iter() {
        option = get_yaml(option, x.to_string())
    }
    if option.is_some() {
        return option.unwrap()
    }
    panic!(format!("in application.yml key: '{}' not exist!", key))
}

fn get_yaml(yaml: Option<&Yaml>, key: String) -> Option<&Yaml>{
    match yaml.unwrap() {
        Yaml::Hash(hash) => {
            return hash.get(&Yaml::String(key.to_string()));
        }
        _ => {}
    }
    yaml
}
